package data.xml;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.map.MapBuilder;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.XmlUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.junit.Assert;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.xpath.XPathConstants;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Slf4j
public class HutoolTest {
    /**
     * 读测试
     */
    @Test
    public void t1() {
        ClassPathResource resource = new ClassPathResource("xml/test1.xml");
        String content = resource.readUtf8Str();
        System.out.println(content);
    }

    /**
     * 简单元素解析
     */
    @Test
    public void parse() {
        ClassPathResource resource = new ClassPathResource("xml/hutool/test1.xml");
        String content = resource.readUtf8Str();
        Document docResult = XmlUtil.parseXml(content);
        String elementText = XmlUtil.elementText(docResult.getDocumentElement(), "returnstatus");
        System.out.println(elementText);
    }

    /**
     * xml to Map
     * {returnstatus=Success, successCounts=1, message=ok, remainpoint=1490, taskID=885}
     */
    @Test
    public void xml2Map() {
        ClassPathResource resource = new ClassPathResource("xml/hutool/xmlToMap.xml");
        String content = resource.readUtf8Str();
        Map<String, Object> map = XmlUtil.xmlToMap(content);
        System.out.println(map);
    }

    /**
     *
     */
    @Test
    public void xml2Map2() {
        ClassPathResource resource = new ClassPathResource("xml/hutool/user.xml");
        String user = resource.readUtf8Str();
        Map<String, Object> map = XmlUtil.xmlToMap(user);
        List list = (List) map.get("name");
        System.out.println(list.toString());
    }

    /**
     * MapToXML
     * <?xml version="1.0" encoding="UTF-8" standalone="no"?>
     * <user>
     * <name>张三</name>
     * <age>12</age>
     * <game>
     * <昵称>Looly</昵称>
     * <level>14</level>
     * </game>
     * </user>
     */
    @Test
    public void Map2Xml() {
        Map<String, Object> map = MapBuilder.create(new LinkedHashMap<String, Object>())//
                .put("name", "张三")//
                .put("age", 12)//
                .put("game", MapUtil.builder(new LinkedHashMap<String, Object>()).put("昵称", "Looly").put("level", 14).build())//
                .build();
        Document doc = XmlUtil.mapToXml(map, "user");
        System.out.println(XmlUtil.toStr(doc));
    }

    /**
     * <?xml version="1.0" encoding="UTF-8" standalone="no"?>
     * <City>
     * <Town>town1</Town>
     * <Town>town2</Town>
     * </City>
     */
    @Test
    public void Map2Xml2() {
        // 测试List
        Map<String, Object> map = MapBuilder.create(new LinkedHashMap<String, Object>())
                .put("Town", CollUtil.newArrayList("town1", "town2"))
                .build();
        Document doc = XmlUtil.mapToXml(map, "City");
        System.out.println(XmlUtil.toStr(doc));
    }

    /**
     * write 测试
     */
    @Test
    public void write() {
        String result = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>"//
                + "<returnsms>"//
                + "<returnstatus>Success（成功）</returnstatus>"//
                + "<message>ok</message>"//
                + "<remainpoint>1490</remainpoint>"//
                + "<taskID>885</taskID>"//
                + "<successCounts>1</successCounts>"//
                + "</returnsms>";
        Document docResult = XmlUtil.parseXml(result);
        XmlUtil.toFile(docResult, "D:/aaa.xml", "utf-8");
    }

    /**
     * xpath 解析
     * ok
     */
    @Test
    public void xpath() {
        ClassPathResource resource = new ClassPathResource("xml/hutool/xpath.xml");
        String content = resource.readUtf8Str();
        Document docResult = XmlUtil.parseXml(content);
        Object value = XmlUtil.getByXPath("//returnsms/message", docResult, XPathConstants.STRING);
        System.out.println(value);
    }

    // xpath 测试2
    @Test
    public void xpath2() {
        String result = ResourceUtil.readUtf8Str("xml/hutool/xpath.xml");
        Document docResult = XmlUtil.parseXml(result);
        Object value = XmlUtil.getByXPath("//returnsms/returnstatus", docResult, XPathConstants.STRING);
        System.out.println(value);
    }

    /**
     * Sax 解析
     */
    @Test
    public void readBySaxTest() {
        final Set<String> eles = CollUtil.newHashSet(
                "returnsms", "returnstatus", "message", "remainpoint", "taskID", "successCounts");
        XmlUtil.readBySax(ResourceUtil.getStream("xml/hutool/test1.xml"), new DefaultHandler() {
            @Override
            public void startElement(String uri, String localName, String qName, Attributes attributes) {
                log.info("uri:{},localName:{},qName:{}", uri, localName, qName);
                int length = attributes.getLength();
                for (int i = 0; i < length; i++) {
                    System.out.println(attributes.getValue(i));
                }
            }
        });
    }

    /**
     * map 转 xmlStr
     */
    @Test
    public void mapToXmlTestWithOmitXmlDeclaration() {

        Map<String, Object> map = MapBuilder.create(new LinkedHashMap<String, Object>())
                .put("name", "ddatsh")
                .build();
        String xml = XmlUtil.mapToXmlStr(map, true);
        Assert.assertEquals("<xml><name>ddatsh</name></xml>", xml);
    }

    @Test
    public void mapToXmlTestWithNoOmitXmlDeclaration() {
        Map<String, Object> map = MapBuilder.create(new LinkedHashMap<String, Object>())
                .put("name", "ddatsh")
                .build();
        String xml2 = XmlUtil.mapToXmlStr(map, false);
        Assert.assertEquals("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><xml><name>ddatsh</name></xml>", xml2);
    }


    /**
     * <?xml version="1.0" encoding="UTF-8"?>
     * <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
     * <soap:Body>
     * <ns2:testResponse xmlns:ns2="http://ws.xxx.com/">
     * <return>2020/04/15 21:01:21</return>
     * </ns2:testResponse>
     * </soap:Body>
     * </soap:Envelope>
     */
    @Test
    public void getByPathTest() {
        String xmlStr = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
                "  <soap:Body>\n" +
                "    <ns2:testResponse xmlns:ns2=\"http://ws.xxx.com/\">\n" +
                "      <return>2020/04/15 21:01:21</return>\n" +
                "    </ns2:testResponse>\n" +
                "  </soap:Body>\n" +
                "</soap:Envelope>\n";
        System.out.println(xmlStr);
        Document document = XmlUtil.readXML(xmlStr);
        Object value = XmlUtil.getByXPath(
                "//soap:Envelope/soap:Body/ns2:testResponse/return",
                document, XPathConstants.STRING);//
        Assert.assertEquals("2020/04/15 21:01:21", value);
    }


    /**
     * bean转XML,包括命名空间
     * <?xml version="1.0" encoding="UTF-8" standalone="no"?>
     * <TestBean>
     * <ReqCode>1111</ReqCode>
     * <AccountName>账户名称</AccountName>
     * <Operator>cz</Operator>
     * <ProjectCode>123</ProjectCode>
     * <BankCode>00001</BankCode>
     * </TestBean>
     */
    @Test
    public void xmlToBeanTest() {
        final TestBean testBean = new TestBean();
        testBean.setReqCode("1111");
        testBean.setAccountName("账户名称");
        testBean.setOperator("cz");
        testBean.setProjectCode("123");
        testBean.setBankCode("00001");

        final Document doc = XmlUtil.beanToXml(testBean/*,"ls"*/);
        System.out.println(XmlUtil.toStr(doc));
        Assert.assertEquals(TestBean.class.getSimpleName(), doc.getDocumentElement().getTagName());

        final TestBean testBean2 = XmlUtil.xmlToBean(doc, TestBean.class);
        Assert.assertEquals(testBean.getReqCode(), testBean2.getReqCode());
        Assert.assertEquals(testBean.getAccountName(), testBean2.getAccountName());
        Assert.assertEquals(testBean.getOperator(), testBean2.getOperator());
        Assert.assertEquals(testBean.getProjectCode(), testBean2.getProjectCode());
        Assert.assertEquals(testBean.getBankCode(), testBean2.getBankCode());
    }

    /**
     * 清除注释
     */
    @Test
    public void cleanCommentTest() {
        final String xmlContent = "<info><title>hutool</title><!-- 这是注释 --><lang>java</lang></info>";
        final String ret = XmlUtil.cleanComment(xmlContent);
        Assert.assertEquals("<info><title>hutool</title><lang>java</lang></info>", ret);
    }


    @Data
    public static class TestBean {
        private String ReqCode;
        private String AccountName;
        private String Operator;
        private String ProjectCode;
        private String BankCode;
    }


    // ----------------------------------- 扩展测试 ---------------------------

    /**
     * 集合解析测试
     */
    @Test
    public void ex2() {
        ClassPathResource resource = new ClassPathResource("xml/test2.xml");
        String content = resource.readUtf8Str();
        final Document document = XmlUtil.parseXml(content);
        final List<Element> sms = XmlUtil.getElements(document.getDocumentElement(), "sms");
        sms.forEach(e -> {
            final String adress = XmlUtil.elementText(e, "adress");
            System.out.println(adress);
        });
    }


}
